package com.gitee.li709.jmeter.client;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import com.gitee.li709.jmeter.JmeterTest;
import com.gitee.li709.jmeter.SampleResultManager;
import com.gitee.li709.jmeter.event.ChatBaseEventImpl;
import com.gitee.li709.jmeter.event.ChatMessageEventImpl;
import com.gitee.li709.jmeter.event.MessageQoSEventImpl;
import net.x52im.mobileimsdk.server.protocal.Protocal;
import net.x52im.mobileimsdk.server.protocal.c.PLoginInfo;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;


public class NettyClient {
    private String name;
    private boolean isLogin=false;
    private String accid;
    private String token;
    private int timeOutMillisecond;
    private Protocal protocal=null;
    private ClientCoreSDK clientCoreSDK;
    private ConfigEntity configEntity;
    private LocalSocketProvider localSocketProvider;
    private SampleResultManager sampleResultManager;
    private LocalDataReciever localDataReciever;
    private KeepAliveDaemon keepAliveDaemon;
    private AutoReLoginDaemon autoReLoginDaemon;
    private QoS4ReciveDaemon qoS4ReciveDaemon;
    private QoS4SendDaemon qoS4SendDaemon;
    private LocalDataSender localDataSender;
    private Field fp = ReflectUtil.getField(Protocal.class, "fp");


    public NettyClient(String name,JavaSamplerContext context){
        accid = context.getParameter(JmeterTest.ACCID_NAME);
        timeOutMillisecond = Integer.parseInt(context.getParameter(JmeterTest.TIME_OUT_MILLISECOND_NAME));
        this.name=accid+"="+name;
        System.out.println("初始化"+name);
        token = context.getParameter(JmeterTest.TOKEN_NAME);
        String protocalStr = context.getParameter(JmeterTest.PROTOCAL_NAME);
        protocal= JSONUtil.toBean(protocalStr, Protocal.class);

        sampleResultManager=new SampleResultManager(this);
        configEntity=new ConfigEntity();
        //初始化客户端连接
        configEntity.setSenseMode(ConfigEntity.SenseMode.MODE_5S);
        configEntity.serverIP = context.getParameter(JmeterTest.IP_NAME);
        configEntity.serverPort = Integer.parseInt(context.getParameter(JmeterTest.PORT_NAME));

        clientCoreSDK=new ClientCoreSDK(this);
        clientCoreSDK.setChatBaseEvent(new ChatBaseEventImpl(this));
        clientCoreSDK.setChatMessageEvent(new ChatMessageEventImpl(this));
        clientCoreSDK.setMessageQoSEvent(new MessageQoSEventImpl(this));

        localSocketProvider=new LocalSocketProvider(this);
        localDataReciever=new LocalDataReciever(this);
        keepAliveDaemon=new KeepAliveDaemon(this);
        autoReLoginDaemon=new AutoReLoginDaemon(this);
        qoS4ReciveDaemon=new QoS4ReciveDaemon(this);
        qoS4SendDaemon=new QoS4SendDaemon(this);
        localDataSender=new LocalDataSender(this);
    }

    public void sendMsg(JavaSamplerContext context){
        String protocalStr = context.getParameter(JmeterTest.PROTOCAL_NAME);
        protocal= JSONUtil.toBean(protocalStr, Protocal.class);
        ReflectUtil.setFieldValue(protocal,fp,Protocal.genFingerPrint());

        try {
            checkLogin();
            CountDownLatch countDownLatch = sampleResultManager.init(protocal.toGsonString());
            System.out.println("发送消息包："+name+"=="+protocal.getFp());
            localDataSender.sendCommonData(protocal);
            boolean await = countDownLatch.await(timeOutMillisecond, TimeUnit.MILLISECONDS);
            if (!await){
                sampleResultManager.end("请求超时","500","ack请求超时"+protocal.getFp());
            }
        } catch (Exception e) {
            sampleResultManager.addRawSubResult("系统异常", 500 + "", e.toString(),false);
        }
    }

    private void checkLogin() throws InterruptedException {
        if (!isLogin){
            CountDownLatch loginSuccess= ThreadUtil.newCountDownLatch(1);
            localSocketProvider.resetLocalSocket();
            System.out.println("准备发送登陆"+Thread.currentThread().getName());
            Thread.sleep(300);
            isLogin=true;
            //发送登陆请求
            PLoginInfo loginInfo = new PLoginInfo(accid, token);
            // * 异步提交登陆名和密码
            new LocalDataSender.SendLoginDataAsync(this,loginInfo){
                @Override
                protected void fireAfterSendLogin(int code) {
                    loginSuccess.countDown();
                }
            }.execute();
            boolean await = loginSuccess.await(timeOutMillisecond, TimeUnit.MILLISECONDS);
            if (!await){
                sampleResultManager.end("登陆请求超时","500","ack请求超时"+loginInfo.getLoginUserId());
            }
        }
    }

    public void release(){
        isLogin=false;
        getClientCoreSDK().release();
        System.out.println(name+"连接释放!!!");
    }

    public String getName() {
        return name;
    }

    public ClientCoreSDK getClientCoreSDK() {
        return clientCoreSDK;
    }

    public LocalSocketProvider getLocalSocketProvider() {
        return localSocketProvider;
    }

    public SampleResultManager getSampleResultManager() {
        return sampleResultManager;
    }

    public ConfigEntity getConfigEntity() {
        return configEntity;
    }

    public LocalDataReciever getLocalDataReciever() {
        return localDataReciever;
    }

    public KeepAliveDaemon getKeepAliveDaemon() {
        return keepAliveDaemon;
    }

    public AutoReLoginDaemon getAutoReLoginDaemon() {
        return autoReLoginDaemon;
    }

    public QoS4ReciveDaemon getQoS4ReciveDaemon() {
        return qoS4ReciveDaemon;
    }

    public QoS4SendDaemon getQoS4SendDaemon() {
        return qoS4SendDaemon;
    }

    public LocalDataSender getLocalDataSender() {
        return localDataSender;
    }
}
